//#include <bits/stdc++.h>
//using namespace std;
//#define int long long
//const int mod = 1000000007;
//const int N = 110;
//int n, m;
//int mem[N][N][N]; // 记忆化数组
//int dfs(int svn, int svm, int svt) {
//    if (svn == 0 && svm == 0 && svt == 1) return 1; // 正确终止条件
//    if (svn < 0 || svm < 0 || svt < 1) return 0;
//    if (mem[svn][svm][svt]!=-1) return mem[svn][svm][svt];
//    if (svt-1 > svm) return  0; // 正确剪枝
//
//    int ret = 0;
//    // 选择店
//    int new_w = 2 * svt;
//    if (new_w-1<= svm) { // 合法性检查
//        ret = (ret + dfs(svn - 1, svm, new_w)) % mod;
//    }
//    // 选择花
//    if (svt >= 1) {
//        ret = (ret + dfs(svn, svm - 1, svt - 1)) % mod;
//    }
//    mem[svn][svm][svt] = ret;
//    return ret;
//}
//
//signed main() {
//    ios_base::sync_with_stdio(0);
//    cin.tie(0);
//    cout.tie(0);
//    cin >> n >> m;
//    memset(mem, -1, sizeof(mem)); // 初始化记忆化数组
//    int ret = dfs(n, m-1, 2); // 正确参数传递（最后一次是花）
//    cout << ret % mod << endl;
//    return 0;
//}
#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int mod=1e9+7;
#define int long long 
int n,m;
int dp[N][N][N];//代表用n个店m个花此时k个斗 
signed main()
{
	//题目转化为给你n，m-1使最后的数为1的方案数 
	//我们要求的是dp[n][m-1][1] 
	cin>>n>>m;
	//合法条件我们的m>=w-1
	dp[0][0][2]=1; 
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=m;j++)
		{
			//我们的合法条件要求斗数-1小于等于我们的花 
			for(int k=0;k<=m;k++)
			{
				if(i==0&&j==0) continue;//此时状态除2都是0 
				if(k%2==0&&i)
				dp[i][j][k]=(dp[i][j][k]+dp[i-1][j][k/2])%mod;
				//选花
				if(j)
				dp[i][j][k]=(dp[i][j][k]+dp[i][j-1][k+1])%mod; 
			}
		}
	 } 
	 cout<<dp[n][m-1][1];
	return 0;
}
